package cn.itcast.n8;

import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.locks.StampedLock;

import static cn.itcast.n2.util.Sleeper.sleep;

@Slf4j(topic = "c.TestStampedLock")
public class TestStampedLock {
    public static void main(String[] args) {

    }
}

@Slf4j(topic = "c.DataContainerStamped")
class DataContainerStamped {

    private int data;
    private final StampedLock lock = new StampedLock();

    public DataContainerStamped(int data) {
        this.data = data;
    }

    public int read(int readTime){
        long stamp = lock.tryOptimisticRead();
        log.debug("optimistic read locking...{}",stamp);
        sleep(readTime);
        if (lock.validate(stamp)) {
            log.debug("read finish...{}", stamp);
            return data;
        }

        log.debug("updating to read lock... {}",stamp);
        try {
            stamp = lock.readLock();
            log.debug("read lock {}", stamp);
            sleep(readTime);
            log.debug("read finish...{}", stamp);
            return data;
        }finally {
            log.debug("read unlock {}",stamp);
            lock.unlock(stamp);
        }
    }


    public void write(int newData){
        final long stamp = lock.writeLock();
        log.debug("write lock {}",stamp);
        try {
            sleep(1);
            this.data = newData;
        }finally {
            log.debug("write unlock {}", stamp);
            lock.unlock(stamp);
        }
    }

}